from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy.orm import Session
from pydantic import BaseModel
from typing import Optional, Any
from decimal import Decimal

from app import crud, models, schemas
from app.api import deps
from app.models.credit_transaction import TransactionType
from app.services.payment_manager import payment_manager
from app.services.payment_base import PaymentProvider, PaymentMethod, PaymentRequest
from app.core.payment_alerts import payment_alert_manager, AlertType, AlertLevel

router = APIRouter()

class RechargeRequest(BaseModel):
    amount: int  # Amount in credits
    payment_provider: PaymentProvider = PaymentProvider.ALIPAY
    payment_method: PaymentMethod = PaymentMethod.H5
    return_url: Optional[str] = None

class PaymentCallbackData(BaseModel):
    order_id: str
    user_id: int
    amount: int
    status: str
    transaction_id: str = None

@router.get("/payment-methods")
def get_payment_methods():
    """获取支持的支付方式"""
    supported_methods = payment_manager.get_supported_methods()
    
    return {
        "payment_methods": [
            {
                "provider": provider.value,
                "provider_name": _get_provider_name(provider),
                "methods": [
                    {
                        "method": method.value,
                        "method_name": _get_method_name(method)
                    } for method in methods
                ]
            }
            for provider, methods in supported_methods.items()
        ]
    }

def _get_provider_name(provider: PaymentProvider) -> str:
    """获取支付提供商中文名"""
    names = {
        PaymentProvider.WECHAT_PAY: "微信支付",
        PaymentProvider.ALIPAY: "支付宝",
        PaymentProvider.STRIPE: "Stripe"
    }
    return names.get(provider, provider.value)

def _get_method_name(method: PaymentMethod) -> str:
    """获取支付方式中文名"""
    names = {
        PaymentMethod.H5: "H5支付",
        PaymentMethod.APP: "APP支付",
        PaymentMethod.NATIVE: "扫码支付",
        PaymentMethod.JSAPI: "公众号支付"
    }
    return names.get(method, method.value)

@router.post("/orders")
async def create_recharge_order(
    *,
    db: Session = Depends(deps.get_db),
    recharge_in: RechargeRequest,
    current_user: models.User = Depends(deps.get_current_user),
) -> Any:
    """
    Create a recharge order.
    """
    if recharge_in.amount <= 0:
        raise HTTPException(status_code=400, detail="Amount must be positive.")
    
    if recharge_in.amount > 10000:
        raise HTTPException(status_code=400, detail="Amount too large. Maximum 10000 credits per transaction.")

    try:
        # 获取支付服务
        payment_service = payment_manager.get_service(recharge_in.payment_provider)
        if not payment_service:
            raise HTTPException(
                status_code=400, 
                detail=f"支付服务不可用: {recharge_in.payment_provider}"
            )
        
        # 生成订单ID
        import time
        order_id = f"recharge_{current_user.id}_{int(time.time())}"
        
        # 创建支付请求
        payment_request = PaymentRequest(
            order_id=order_id,
            amount=Decimal(str(recharge_in.amount)),
            currency="CNY",
            subject=f"画眉AI充值 {recharge_in.amount} 创作点",
            description=f"用户 {current_user.username} 充值创作点",
            user_id=current_user.id,
            payment_method=recharge_in.payment_method,
            return_url=recharge_in.return_url,
            notify_url=f"/api/v1/recharge/callback/{recharge_in.payment_provider.value}"
        )
        
        # 调用支付服务创建订单
        payment_response = await payment_service.create_payment(payment_request)
        
        if not payment_response.success:
            raise HTTPException(
                status_code=400,
                detail=payment_response.error_message or "创建支付订单失败"
            )
        
        # TODO: 将订单信息存储到数据库
        
        response_data = {
            "order_id": order_id,
            "amount": recharge_in.amount,
            "provider": recharge_in.payment_provider.value,
            "method": recharge_in.payment_method.value,
            "status": "pending"
        }
        
        if payment_response.payment_url:
            response_data["payment_url"] = payment_response.payment_url
        
        if payment_response.qr_code:
            response_data["qr_code"] = payment_response.qr_code
            
        if payment_response.payment_data:
            response_data["payment_data"] = payment_response.payment_data
        
        return response_data
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"创建充值订单失败: {str(e)}")

@router.post("/callback/{provider}")
async def handle_recharge_callback(
    provider: str,
    request: Request,
    db: Session = Depends(deps.get_db),
) -> Any:
    """
    Handle callback from payment gateway.
    """
    
    try:
        # 获取支付服务
        payment_provider = PaymentProvider(provider)
        payment_service = payment_manager.get_service(payment_provider)
        
        if not payment_service:
            raise HTTPException(status_code=400, detail=f"不支持的支付提供商: {provider}")
        
        # 获取原始数据
        if request.headers.get("content-type", "").startswith("application/json"):
            raw_data = await request.json()
        else:
            form_data = await request.form()
            raw_data = dict(form_data)
        
        # 处理支付通知
        notification = await payment_service.handle_notification(raw_data)
        
        if not notification:
            # 触发回调处理失败告警
            await payment_alert_manager.trigger_alert(
                AlertType.CALLBACK_PROCESSING_ERROR,
                AlertLevel.HIGH,
                f"支付回调处理失败 - 通知解析失败",
                {
                    "provider": provider,
                    "raw_data_keys": list(raw_data.keys()) if raw_data else [],
                    "error": "通知处理失败"
                },
                provider=provider
            )
            return {"status": "failed", "message": "通知处理失败"}
        
        if notification.status.value == "paid":
            # 查找用户并增加创作点
            user_id = _extract_user_id_from_order(notification.order_id)
            if user_id:
                try:
                    crud.update_user_credits(
                        db,
                        user_id=user_id,
                        amount=int(notification.amount),
                        trans_type=TransactionType.RECHARGE,
                        description=f"充值成功 - {provider} - {notification.transaction_id}"
                    )
                    
                    return {"status": "success", "message": "充值成功"}
                except Exception as credit_error:
                    # 触发积分更新失败告警
                    await payment_alert_manager.trigger_alert(
                        AlertType.CALLBACK_PROCESSING_ERROR,
                        AlertLevel.CRITICAL,
                        f"支付成功但积分更新失败",
                        {
                            "provider": provider,
                            "order_id": notification.order_id,
                            "user_id": user_id,
                            "amount": float(notification.amount),
                            "error": str(credit_error)
                        },
                        provider=provider,
                        order_id=notification.order_id
                    )
                    return {"status": "error", "message": "积分更新失败"}
            else:
                # 触发用户ID提取失败告警
                await payment_alert_manager.trigger_alert(
                    AlertType.CALLBACK_PROCESSING_ERROR,
                    AlertLevel.HIGH,
                    f"无法从订单ID提取用户ID",
                    {
                        "provider": provider,
                        "order_id": notification.order_id,
                        "error": "用户ID提取失败"
                    },
                    provider=provider,
                    order_id=notification.order_id
                )
        
        return {"status": "pending", "message": "支付处理中"}
        
    except Exception as e:
        # 触发通用回调处理错误告警
        await payment_alert_manager.trigger_alert(
            AlertType.CALLBACK_PROCESSING_ERROR,
            AlertLevel.CRITICAL,
            f"支付回调处理异常: {str(e)}",
            {
                "provider": provider,
                "error": str(e),
                "error_type": type(e).__name__
            },
            provider=provider
        )
        return {"status": "error", "message": "处理失败"}

def _extract_user_id_from_order(order_id: str) -> Optional[int]:
    """从订单ID中提取用户ID"""
    try:
        parts = order_id.split("_")
        if len(parts) >= 2:
            return int(parts[1])
    except:
        pass
    return None

@router.get("/orders/{order_id}/status")
async def query_payment_status(
    order_id: str,
    provider: PaymentProvider,
    current_user: models.User = Depends(deps.get_current_user),
) -> Any:
    """查询支付状态"""
    
    try:
        # 验证订单归属
        if not order_id.startswith(f"recharge_{current_user.id}_"):
            raise HTTPException(status_code=403, detail="无权限查询此订单")
        
        payment_service = payment_manager.get_service(provider)
        if not payment_service:
            raise HTTPException(status_code=400, detail=f"支付服务不可用: {provider}")
        
        notification = await payment_service.query_payment(order_id)
        
        if notification:
            return {
                "order_id": order_id,
                "status": notification.status.value,
                "amount": float(notification.amount),
                "transaction_id": notification.transaction_id
            }
        else:
            return {
                "order_id": order_id,
                "status": "unknown",
                "message": "查询失败或订单不存在"
            }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"查询支付状态失败: {str(e)}")

@router.post("/test-recharge/{user_id}")
def test_recharge(
    user_id: int,
    amount: int,
    db: Session = Depends(deps.get_db),
) -> Any:
    """
    测试用充值端点 - 仅供开发测试使用
    生产环境中应删除此端点
    """
    try:
        user = crud.update_user_credits(
            db,
            user_id=user_id,
            amount=amount,
            trans_type=TransactionType.RECHARGE,
            description=f"测试充值 {amount} 创作点"
        )
        
        return {
            "message": f"Successfully added {amount} credits to user {user_id}",
            "new_balance": user.credits_balance
        }
        
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
